#include "ptwrap.hpp"
#include <deque>


// [[ex04ac]]
// DEBUG descr The queue with flow control.
template <class Value>
class Queue
{
public:
	Queue(int limit = 1000) :
		limit_(limit), overcond_(cond_)
	{ }

	virtual ~Queue()
	{ }

	// this combines the STL front() and pop_front()
	// since the popping must be atomic
	Value pop_front()
	{
		pw::lockmutex lm(cond_);

		while(deque_.empty())
			// it releases and gets back the mutex
			cond_.wait(); 

		bool wasonlimit = (deque_.size() == limit_);

		Value v = deque_.front();
		deque_.pop_front();

		if (wasonlimit)
			// we know that the queue is about to become
			// not full
			overcond_.broadcast();

		return v;
	}

	void push_back(Value &v)
	{
		pw::lockmutex lm(cond_);

		while (deque_.size() >= limit_)
			// it releases and gets back the mutex
			overcond_.wait(); 

		bool wasempty = deque_.empty();
		deque_.push_back(v);
		if (wasempty) 
			// we know that the queue has just become
			// non-empty
			cond_.broadcast();
	}

protected:
	int limit_;
	std::deque<Value> deque_;
	pw::pmcond cond_;
	pw::pchaincond overcond_;
};
// END

// DEBUG {
int main()
{
	Queue<int> q;
	int v1 = 1;
	q.push_back(v1);
	int v2 = q.pop_front();
	return !(v1 == v2);
}
// DEBUG }
